package com.ushio.gougouwangguo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ushio.commonmodule.utils.JwtUtil;
import com.ushio.gougouwangguo.entity.mysql.*;
import com.ushio.gougouwangguo.entity.qo.UserTasksQo;
import com.ushio.gougouwangguo.entity.vo.UserTasksVo;
import com.ushio.gougouwangguo.enums.TaskStatusEnum;
import com.ushio.gougouwangguo.mapper.*;
import com.ushio.gougouwangguo.service.IUserTasksService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户任务 服务实现类
 * </p>
 *
 * @author 张文凯
 * @since 2025-09-27
 */
@Service
public class UserTasksServiceImpl extends ServiceImpl<UserTasksMapper, UserTasks> implements IUserTasksService {

    @Autowired
    UserTasksMapper userTasksMapper;

    @Autowired
    ActionConfigMapper actionConfigMapper;
    @Autowired
    DogCharacterMapper dogCharacterMapper;
    @Autowired
    ActionConfigMaterialsMapper actionConfigMaterialsMapper;

    @Autowired
    UserSeasonEventMapper userSeasonEventMapper;

    @Autowired
    UserMaterialsMapper userMaterialsMapper;
    private static final int DUE_LIMIT = 1;


    @Override
    public List<UserTasksVo> saveTheHeartbeat(UserTasksQo userTasksQo) {

        Long userId = userTasksQo.getUserId();
        // 当前时间
        long nowMs = Instant.now().toEpochMilli();
        LocalDateTime now = LocalDateTime.now();

        // 查询该用户的所有运行中任务
        List<UserTasks> running = userTasksMapper.selectList(
                new LambdaQueryWrapper<UserTasks>()
                        .eq(UserTasks::getUserId, userId)
                        .eq(UserTasks::getStatus, TaskStatusEnum.RUNNING.getValue())
        );

        List<UserTasksVo> userTasksVoList = new ArrayList<>();

        for (UserTasks userTasks : running) {

            // 1️⃣ 构建任务 VO
            UserTasksVo userTasksVo = UserTasksVo.builder().build();
            BeanUtils.copyProperties(userTasks, userTasksVo);

            // 2️⃣ 加载角色信息（如果有关联角色）
            DogCharacter dogCharacter = dogCharacterMapper.selectById(userTasksVo.getCharacterId());
            userTasksVo.setDogCharacter(dogCharacter);

            // 3️⃣ 时间信息
            LocalDateTime startedAt = userTasks.getStartedAt();
            LocalDateTime lastProcessedAt = userTasks.getLastProcessedAt();

            // 4️⃣ 获取任务周期（⚠️ 实际单位是“秒”）
            Integer intervalSec = userTasks.getIntervalMs();

            if (intervalSec == null || intervalSec <= 0) {
                continue; // 无效任务周期直接跳过
            }

            // 转换为毫秒用于计算
            long intervalMs = intervalSec * 1000L;

            // 5️⃣ 计算从任务开始到现在经过的时间（毫秒）
            long startMs = toMs(startedAt);
            long elapsedMs = nowMs - startMs;
            if (elapsedMs < 0) elapsedMs = 0;

            // 6️⃣ 已完成多少轮（整数）
            long due = Math.min(elapsedMs / intervalMs, DUE_LIMIT);

            // 当前轮剩余时间
            long remainderMs = elapsedMs % intervalMs;

            // 7️⃣ 计算当前进度百分比
            int progressPercent;
            if (due >= 1) {
                // 已满一轮，刚完成 → 归 0
                LocalDateTime nextTime = startedAt.plusSeconds(intervalSec);
                userTasksVo.setDeadline(nextTime);
                progressPercent = 0;
            } else {

                progressPercent = (int) Math.round((double) remainderMs * 100 / intervalMs);

                userTasksVo.setDeadline(now);

            }
            userTasksVo.setProgress(progressPercent);
            userTasksVoList.add(userTasksVo);

            // 8️⃣ 如果还没到一个完整周期，则不执行奖励发放逻辑
            if (due <= 0) {
                continue;
            }

            // 9️⃣ 查询当前任务对应的材料产出配置
            LambdaQueryWrapper<ActionConfigMaterials> materialsQuery = new LambdaQueryWrapper<>();
            materialsQuery.eq(ActionConfigMaterials::getActionConfigId, userTasks.getTaskId());
            List<ActionConfigMaterials> materialList = actionConfigMaterialsMapper.selectList(materialsQuery);

            // 🔟 根据 due（完成轮次）发放奖励材料
            for (ActionConfigMaterials material : materialList) {
                Integer amount = material.getAmount();
                if (amount == null || amount <= 0) continue;

                UserMaterials stock = UserMaterials.builder()
                        .userId(userTasksQo.getUserId())
                        .materialsId(material.getMaterialsId())
                        .stock(amount * due) // 每轮产出 * 轮数
                        .build();

                userMaterialsMapper.updataUserResources(stock);
            }

            // 11️⃣ 更新时间锚点（相当于任务结算后重置）
            userTasks.setLastProcessedAt(now);
            userTasks.setStartedAt(now);

            // 12️⃣ 持久化更新任务状态
            userTasksMapper.updateById(userTasks);
        }

        LocalDateTime maxDeadline = userTasksVoList.stream()
                .map(UserTasksVo::getDeadline)
                .filter(Objects::nonNull) // 过滤掉 null 值（防止空指针）
                .max(LocalDateTime::compareTo)
                .orElse(null);
        UserSeasonEvent userSeasonEvent = UserSeasonEvent.builder().userId(userId).seasonCurrentTime(maxDeadline).build();
        LambdaQueryWrapper<UserSeasonEvent> userSeasonEventLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userSeasonEventLambdaQueryWrapper.eq(UserSeasonEvent::getUserId,userId);
        userSeasonEventMapper.update(userSeasonEvent,userSeasonEventLambdaQueryWrapper);

        return userTasksVoList;
    }

    /**
     * LocalDateTime 转毫秒
     */
    private long toMs(LocalDateTime time) {
        if (time == null) return 0L;
        return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }


    @Override
    public UserTasksVo saveUserTasks(UserTasksQo userTasksQo) {

        //需求参数 userId 用户id taskId 任务id characterId 指定角色id

        // 1) 查周期（秒 -> 毫秒）
        //通过任务id查询出任务配置任务配置信息
        ActionConfig actionConfig = actionConfigMapper.selectById(userTasksQo.getTaskId());
        int intervalMs = actionConfig.getConsumeTime();

        LocalDateTime now = LocalDateTime.now();

        UserTasks userTasks = UserTasks.builder().build();

        BeanUtils.copyProperties(userTasksQo,userTasks);

        LocalDateTime endAt = now.plusSeconds(intervalMs);

        userTasks.setEndAt(endAt);



        LambdaQueryWrapper<UserTasks> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        lambdaQueryWrapper.eq(UserTasks::getUserId,userTasks.getUserId());
        lambdaQueryWrapper.eq(UserTasks::getTaskId,userTasks.getTaskId());
        lambdaQueryWrapper.last("FOR UPDATE");


        UserTasks userTasksVo = userTasksMapper.selectOne(lambdaQueryWrapper);

        if (userTasksVo == null) {
            // 新建
            userTasksVo = UserTasks.builder()
                    .userId(userTasks.getUserId())
                    .taskId(userTasks.getTaskId())
                    .characterId(userTasks.getCharacterId())
                    .intervalMs(intervalMs)
                    .startedAt(now)         // ✅ 重置为 now
                    .lastProcessedAt(now)   // ✅ 重置为 now
                    .endAt(endAt)
                    .status(TaskStatusEnum.RUNNING.getValue())  // 枚举/字符串都行
                    .build();
            userTasksMapper.insert(userTasksVo);
        } else {
            LocalDateTime lastProcessedAt = userTasksVo.getLastProcessedAt();

            LocalDateTime expirationTime = lastProcessedAt.plusSeconds(intervalMs);
            if (expirationTime.isBefore(now) || expirationTime.isEqual(now)) {
                userTasksVo.setStartedAt(now);         // ✅ 重置为 now
                userTasksVo.setLastProcessedAt(now);
            }
            // 更新为“重新开始”
            userTasksVo.setCharacterId(userTasks.getCharacterId());
            userTasksVo.setIntervalMs(intervalMs);
            userTasksVo.setEndAt(endAt);
            userTasksVo.setStatus(TaskStatusEnum.RUNNING.getValue());
            userTasksMapper.updateById(userTasksVo);
        }
        // 4) 组装返回给前端
        return UserTasksVo.builder()
                .taskId(userTasksVo.getTaskId())
                .intervalMs(userTasksVo.getIntervalMs())
                .startedAt(userTasksVo.getStartedAt())
                .status(userTasksVo.getStatus())
                .build();
    }

    @Override
    public UserTasksVo stopTheHeartbeat(UserTasksQo userTasksQo) {

        Long userId = JwtUtil.parseUser().getUserId();

        LambdaQueryWrapper<UserTasks> tasksLambdaQueryWrapper = new LambdaQueryWrapper<>();

        tasksLambdaQueryWrapper.eq(UserTasks::getUserId,userId);
        tasksLambdaQueryWrapper.eq(UserTasks::getTaskId,userTasksQo.getTaskId());

        UserTasks userTasks = UserTasks.builder().build();

        userTasks.setStatus(TaskStatusEnum.STOPPED.getValue());

        userTasks.setUserId(userId);

        userTasks.setTaskId(userTasksQo.getTaskId());

//        UserTasks userTasks = userTasksMapper.selectOne(tasksLambdaQueryWrapper);

        userTasksMapper.update(userTasks,tasksLambdaQueryWrapper);

        UserTasksVo userTasksVo = UserTasksVo.builder().build();

        BeanUtils.copyProperties(userTasks,userTasksVo);

        return userTasksVo;
    }

    private  long toMs(LocalDateTime lastProcessedAt, LocalDateTime startedAt) {
        LocalDateTime base = (lastProcessedAt != null ? lastProcessedAt : startedAt);
//        return base.toInstant(ZoneOffset.UTC).toEpochMilli();
        return base.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
}
